package com.gome.ocean;


import java.math.BigInteger;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

import com.alibaba.fastjson.JSONArray;
import com.gome.framework.AppContext;
import com.gome.framework.Env;
import com.gome.framework.logging.Logger;
import com.gome.framework.logging.LoggerFactory;
import com.gome.framework.util.CodecUtil;
import com.gome.framework.util.StringUtil;
import com.gome.framework.util.UrlUtil;

/**
 * 
 *
 * @author fuhaining
 */
public class DBAUtil {
	
	private static final Logger LOG = LoggerFactory.getLogger(DBAUtil.class);
	
	private static RestTemplate restTemplate = new RestTemplate();
	
	public static boolean changeDBPwd(String dbType,String dbIp,Integer dbPort, String dbName, String dbUser, String dbPwd) {
		if ("oracle".equalsIgnoreCase(dbType)) {
			try {
				return changeDBPwd(dbType, dbIp, dbPort, dbName, "service_name", dbUser, dbPwd);
			} catch (IllegalStateException e) {
				if (e.getMessage().indexOf("ORA-12505") != -1) {
					return changeDBPwd(dbType, dbIp, dbPort, dbName, "sid", dbUser, dbPwd);
				} else {
					throw e;
				}
			}
		} else {
			return changeDBPwd(dbType, dbIp, dbPort, dbName, "", dbUser, dbPwd);
		}
	}
	
	public static boolean changeDBPwd(String dbType,String dbIp,Integer dbPort, String dbName, String dbNameType, String dbUser, String dbPwd) {
		Env env = AppContext.getEnv();
		String key = env.getProperty("dba.key"); // 秘钥
		String source = env.getProperty("dba.source");
		long timestamp = System.currentTimeMillis();
		String ciphertext = encrypt(dbPwd, key);
		String sign = CodecUtil.md5(dbType + dbIp + dbPort + dbName + dbNameType + dbUser + ciphertext + source + timestamp + key);
		String url = env.getProperty("dba.changeDBPwd.url");
		
		String encoding = "UTF-8";
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.parseMediaType("application/x-www-form-urlencoded; charset=" + encoding));
		HttpEntity<String> request = new HttpEntity<String>(
			"dbType=" + UrlUtil.encode(dbType, encoding) 
			+ "&dbIp=" + UrlUtil.encode(dbIp, encoding)
			+ "&dbPort=" + dbPort
			+ "&dbName=" + UrlUtil.encode(dbName, encoding)
			+ "&dbNameType=" + UrlUtil.encode(dbNameType, encoding)
			+ "&dbUser=" + UrlUtil.encode(dbUser, encoding)
			+ "&dbPwd=" + UrlUtil.encode(ciphertext, encoding)
			+ "&source=" + UrlUtil.encode(source, encoding)
			+ "&timestamp=" + timestamp
			+ "&sign=" + UrlUtil.encode(sign, encoding)
		, headers);
		
		ResponseEntity<String> response = restTemplate.postForEntity(url, request, String.class);
		if (response.getStatusCode().equals(HttpStatus.OK)) {
			String body = response.getBody();
			if ("success".equalsIgnoreCase(body)) {
				return true;
			} else {
				throw new IllegalStateException("修改数据库密码错误， " + body);
			}
		}
		
		return false;
	}
	
	
	
	private static String encrypt(String plaintext, String key) {
		if (StringUtil.isBlank(plaintext)) {
			throw new IllegalArgumentException("参数plaintext不能为空");
		}
		
		try {
			SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), "AES");
			Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
			cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
			byte[] ciphertextBytes = cipher.doFinal(plaintext.getBytes());
			
			return CodecUtil.hexEncode(ciphertextBytes);
		} catch (Exception e) {
			throw new IllegalArgumentException(e.getMessage(), e);
		}
	}
	
	private static String decrypt(String ciphertext, String key) {
        if (StringUtils.isBlank(ciphertext)) {
            throw new IllegalArgumentException("参数ciphertext不能为空");
        }
        if (StringUtils.isBlank(key)) {
            throw new IllegalArgumentException("参数key不能为空");
        }
        if (key.length() != 21) {
            throw new IllegalArgumentException("参数错误");
        }

        try {
            key = key.substring(2, 18);
            SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), "AES");
            byte[] ciphertextBytes = parseHexStr2Byte(ciphertext);
            Cipher cipher = Cipher.getInstance("AES");
            cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
            byte[] plaintextBytes = cipher.doFinal(ciphertextBytes);
            String plaintext = new String(plaintextBytes);

            return plaintext;
        } catch (Exception e) {
            throw new IllegalArgumentException(e.getMessage(), e);
        }
    }
	
	public static byte[] parseHexStr2Byte(String hexStr){  
        if(hexStr.length() < 1)  
            return null;  
        byte[] result = new byte[hexStr.length()/2];  
        for (int i = 0;i< hexStr.length()/2; i++) {  
            int high = Integer.parseInt(hexStr.substring(i*2, i*2+1), 16);  
            int low = Integer.parseInt(hexStr.substring(i*2+1, i*2+2), 16);  
            result[i] = (byte) (high * 16 + low);  
        }  
        return result;  
    }
	
	public static void main(String[] args) {
//		boolean r = changeDBPwd("mysql", "10.126.53.192", 7307, "gmonitor", "prd_tr_test22", "666666");
//		boolean r = changeDBPwd("oracle", "10.126.53.192", 31521, "gamp_test", "prd_tr_test35", "666666");
//		System.out.println(r);
		
	    JSONArray json = JSONArray.parseArray("[{\"data\":\"cp1257_lithuanian_ci\",\"label\":\"cp1257_lithuanian_ci\"},{\"data\":\"cp1257_bin\",\"label\":\"cp1257_bin\"},{\"data\":\"cp1257_general_ci\",\"label\":\"cp1257_general_ci\"}]");
	    System.out.println(json);
		String ciphertext = decrypt("f51dbd8ad0d3fed1378fab9dff61e46cf5c21d626818a22a79308294b6f532ab", "");
		System.out.println(ciphertext);
	}
}